﻿using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Data;
using Microsoft.SharePoint.Workflow;

namespace AdminPack.WorkflowManager
{
    [ToolboxItemAttribute(false)]
    public class WorkflowManager : WebPart
    {
        private bool _error = false;
        /// <summary>
        /// Store the results in this SPGridView
        /// </summary>
        private SPGridView gvTheList;
        /// <summary>
        /// Primarily for displaying error message
        /// </summary>
        private Label lblStatus;
        /// <summary>
        /// Data source for gvTheList
        /// </summary>
        private ObjectDataSource dsTheList;

        public WorkflowManager()
        {
            this.ExportMode = WebPartExportMode.All;
        }
        protected override void CreateChildControls()
        {
            if (!_error)
            {
                try
                {
                    base.CreateChildControls();

                    //create the label object
                    lblStatus = new Label();
                    lblStatus.CssClass = "ms-alert";
                    this.Controls.Add(lblStatus);

                    //create the SPGridView object
                    const string GRIDID = "gvTheList";
                    const string DATASOURCEID = "dsTheList";

                    //ref http://www.reversealchemy.net/2009/05/01/building-a-spgridview-control-part-1-introducing-the-spgridview/
                    //create a datasource for the spgridview for filtering
                    dsTheList = new ObjectDataSource();
                    dsTheList.ID = DATASOURCEID;
                    dsTheList.SelectMethod = "LoadList";
                    dsTheList.TypeName = this.GetType().AssemblyQualifiedName;
                    dsTheList.ObjectCreating += new ObjectDataSourceObjectEventHandler(dsTheList_ObjectCreating);
                    this.Controls.Add(dsTheList);

                    gvTheList = new SPGridView();
                    gvTheList.ID = GRIDID;
                    gvTheList.DataSourceID = dsTheList.ID;
                    gvTheList.AutoGenerateColumns = false;
                    gvTheList.Width = Unit.Percentage(100);
                    gvTheList.AllowSorting = true;
                    gvTheList.AllowFiltering = true;

                    //ref http://www.reversealchemy.net/2009/05/24/building-a-spgridview-control-part-2-filtering/
                    //filtering
                    gvTheList.FilterDataFields = "Workflow,Name,State,RunManual,RunCreate,RunChange,Running,Site,ListName"; //in order of columns below
                    gvTheList.FilteredDataSourcePropertyName = "FilterExpression";
                    gvTheList.FilteredDataSourcePropertyFormat = "{1} like '{0}'";

                    //load columns and allow sorting
                    BoundField fldWorkflow = new BoundField();
                    fldWorkflow.DataField = "Workflow";
                    fldWorkflow.HeaderText = "Workflow Template";
                    fldWorkflow.SortExpression = "Workflow";
                    gvTheList.Columns.Add(fldWorkflow);

                    HyperLinkField fldName = new HyperLinkField();
                    fldName.DataTextField = "Name";
                    fldName.HeaderText = "Workflow Name";
                    fldName.SortExpression = "Name";
                    fldName.DataNavigateUrlFields = new string[] { "NameURL" };
                    fldName.DataNavigateUrlFormatString = "{0}";
                    gvTheList.Columns.Add(fldName);

                    HyperLinkField fldState = new HyperLinkField();
                    fldState.DataTextField = "State";
                    fldState.HeaderText = "Enabled";
                    fldState.SortExpression = "State";
                    fldState.DataNavigateUrlFields = new string[] { "StateURL" };
                    fldState.DataNavigateUrlFormatString = "{0}";
                    gvTheList.Columns.Add(fldState);

                    HyperLinkField fldRunManual = new HyperLinkField();
                    fldRunManual.DataTextField = "RunManual";
                    fldRunManual.HeaderText = "Run Manual";
                    fldRunManual.SortExpression = "RunManual";
                    fldRunManual.DataNavigateUrlFields = new string[] { "NameURL" };
                    fldRunManual.DataNavigateUrlFormatString = "{0}";
                    gvTheList.Columns.Add(fldRunManual);

                    HyperLinkField fldRunCreate = new HyperLinkField();
                    fldRunCreate.DataTextField = "RunCreate";
                    fldRunCreate.HeaderText = "On Create";
                    fldRunCreate.SortExpression = "RunCreate";
                    fldRunCreate.DataNavigateUrlFields = new string[] { "NameURL" };
                    fldRunCreate.DataNavigateUrlFormatString = "{0}";
                    gvTheList.Columns.Add(fldRunCreate);

                    HyperLinkField fldRunChange = new HyperLinkField();
                    fldRunChange.DataTextField = "RunChange";
                    fldRunChange.HeaderText = "On Change";
                    fldRunChange.SortExpression = "RunChange";
                    fldRunChange.DataNavigateUrlFields = new string[] { "NameURL" };
                    fldRunChange.DataNavigateUrlFormatString = "{0}";
                    gvTheList.Columns.Add(fldRunChange);

                    BoundField fldRunning = new BoundField();
                    fldRunning.DataField = "Running";
                    fldRunning.HeaderText = "Running";
                    fldRunning.SortExpression = "Running";
                    gvTheList.Columns.Add(fldRunning);

                    BoundField fldSite = new BoundField();
                    fldSite.DataField = "Site";
                    fldSite.HeaderText = "Site";
                    fldSite.SortExpression = "Site";
                    gvTheList.Columns.Add(fldSite);

                    HyperLinkField fldList = new HyperLinkField();
                    fldList.DataTextField = "ListName";
                    fldList.HeaderText = "List";
                    fldList.SortExpression = "ListName";
                    fldList.DataNavigateUrlFields = new string[] { "ListURL" };
                    fldList.DataNavigateUrlFormatString = "{0}";
                    gvTheList.Columns.Add(fldList);
                    this.Controls.Add(gvTheList);
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }


        void dsTheList_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
        {
            e.ObjectInstance = this;
        }

        /// <summary>
        /// Loads the list of workflows
        /// </summary>
        public DataTable LoadList()
        {
            if (!_error)
            {
                try
                {
                    //create the dataset
                    DataTable dt = CreateDataset();

                    //get the site collection
                    using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                    {
                        //loop through all webs in this site
                        foreach (SPWeb web in site.AllWebs)
                        {
                            using (web)
                            {
                                //loop through all lists in this web
                                foreach (SPList list in web.Lists)
                                {
                                    //loop through the workflows on the list
                                    foreach (SPWorkflowAssociation wf in list.WorkflowAssociations)
                                    {
                                        DataRow newRow = dt.NewRow();
                                        if (wf.BaseTemplate == null)
                                            newRow["Workflow"] = "NONE*"; //SharePoint Designer Workflows do not have a template
                                        else
                                            newRow["Workflow"] = wf.BaseTemplate.Name; //get the Workflow template name

                                        newRow["Name"] = wf.Name;
                                        newRow["NameURL"] = web.Url + "/_layouts/AddWrkfl.aspx?List=" + list.ID.ToString() + "&TemplateID=" + wf.Id.ToString();
                                        newRow["Running"] = wf.RunningInstances.ToString();
                                        newRow["State"] = wf.Enabled.ToString();
                                        newRow["StateURL"] = web.Url + "/_layouts/RemWrkfl.aspx?List=" + list.ID.ToString();
                                        newRow["RunManual"] = wf.AllowManual.ToString();
                                        newRow["RunCreate"] = wf.AutoStartCreate.ToString();
                                        newRow["RunChange"] = wf.AutoStartChange.ToString();
                                        newRow["Site"] = web.Title;
                                        newRow["ListName"] = list.Title;
                                        newRow["ListURL"] = list.DefaultViewUrl;
                                        dt.Rows.Add(newRow);
                                    }
                                }
                            }
                        }
                    }

                    return dt;
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                    return null;
                }
            }
            else
                return null;
        }


        /// <summary>
        /// Creates the dataset to store the workflows. 
        /// </summary>
        /// <returns>DataTable</returns>
        private DataTable CreateDataset()
        {
            try
            {
                DataTable dt = new DataTable();
                dt.Columns.Add(new DataColumn("Workflow"));
                dt.Columns.Add(new DataColumn("Name"));
                dt.Columns.Add(new DataColumn("NameURL"));
                dt.Columns.Add(new DataColumn("State"));
                dt.Columns.Add(new DataColumn("StateURL"));
                dt.Columns.Add(new DataColumn("RunManual"));
                dt.Columns.Add(new DataColumn("RunCreate"));
                dt.Columns.Add(new DataColumn("RunChange"));
                dt.Columns.Add(new DataColumn("Running"));
                dt.Columns.Add(new DataColumn("Site"));
                dt.Columns.Add(new DataColumn("ListName"));
                dt.Columns.Add(new DataColumn("ListURL"));

                return dt;
            }
            catch (Exception ex)
            {
                HandleException(ex);
                return new DataTable();
            }
        }
        protected override void OnLoad(EventArgs e)
        {
            if (!_error)
            {
                try
                {
                    base.OnLoad(e);
                    this.EnsureChildControls();
                    gvTheList.DataBind();
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                }
            }
        }
        protected override void RenderContents(HtmlTextWriter w)
        {
            try
            {
                lblStatus.RenderControl(w);
                gvTheList.RenderControl(w);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }

        }
        private void HandleException(Exception ex)
        {
            this._error = true;
            this.Controls.Clear();
            lblStatus.Text = ex.ToString();
        }
    }
}
